﻿using System;

using Sustainalytics.Utils;

using System.Threading.Tasks;
using Xunit;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.MongoDB.Extensions;
using Xunit.Abstractions;
using Sustainalytics.ESGRatings.BusinessLogic.Validators;
using Sustainalytics.Synchronization.Interface;
using System.Collections.Generic;
using System.Collections.Concurrent;
using MongoDB.Driver;
using Sustainalytics.ESG.Entities;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.ESGRatings.BusinessLogic.ESGProfile;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.DataLayer.EsgRatings;

namespace Sustainalytics.ESGRatings.BusinessLogic.Tests
{
    public static class TestSyncContextFactoy
    {
        private const string GaMongoIp = "localhost";
        private const string DsoMongoIp = "52.208.112.211";
        private const string DatabaseGroup = "A";

        public static SyncContext Create(Action<string> log = null)
        {
            var context = new SyncContext(ErrorPolicy.BreakRightAway, log)
            {
                GAConnectionStrings = new Dictionary<string, string>(),
                DSOConnectionStrings = new Dictionary<string, string>(),
                Report = new ConcurrentBag<string>(),
                CompanyUniverses = new Dictionary<Guid, List<int>>(),
                PreviousChanges = new List<ChangedElement>()
            };
            context.GAConnectionStrings["ClientPlatform"] = String.Format("mongodb://{0}:27017/ClientPlatform", GaMongoIp);
            context.GAConnectionStrings["ClientUniverses"] = String.Format("mongodb://{0}:27017/ClientUniverses", GaMongoIp);
            context.GAConnectionStrings["RPHistoricalDataSet"] = string.Format("mongodb://{0}:27017/RPHistoricalDataSet", GaMongoIp);
            context.GAConnectionStrings["ClientDW"] = string.Format("mongodb://{0}:27017/ClientDW_{1}", GaMongoIp, DatabaseGroup);
            context.DSOConnectionStrings["ScreeningDW"] = string.Format("mongodb://{0}:27017/ScreeningDW_{1}", DsoMongoIp, DatabaseGroup);
            context.GAConnectionStrings["DWArchive"] = string.Format("mongodb://{0}:27017/DWArchive_{1}", GaMongoIp, DatabaseGroup);
            context.GAConnectionStrings["ControversyReportPDF"] = string.Format("mongodb://{0}:27017/ControversyReportPDF_{1}", GaMongoIp, DatabaseGroup);
            context.GAConnectionStrings["CompanyReportPDF"] = string.Format("mongodb://{0}:27017/CompanyReportPDF_{1}", GaMongoIp, DatabaseGroup);
            context.GAConnectionStrings["ComputationServiceAddress"] = @"http://54.76.182.88:10280/esgcomputingserv/api/v1";

            return context;
        }
    }


    public class ESGRatingsSyncStepTests
    {
        readonly ITestOutputHelper output;

        public ESGRatingsSyncStepTests(ITestOutputHelper output)
        {
            this.output = output;
        }

        [Fact]
        public void ESGRatingsSyncStepStartTest2()
        {
            var context = TestSyncContextFactoy.Create();

            var step = new ESGRatingsPreparationSyncStep();
            var result = step.Start(context);
            output.WriteLine(result.Report.Dump());

            Xunit.Assert.True(true);
        }


        [Fact]

        public async Task EsgRatingsdefaultReferenceUniverse()
        {
            var context = TestSyncContextFactoy.Create();

            var clientDWConnectionString = context.GAConnectionStrings["ClientDW"];


            var step = new ESGRatingsPreparationSyncStep();

            var corporate = new CorporateDataManagement(
                MongoFactory.GetCollectionFromDatabase<CorporateData>(clientDWConnectionString), 
                MongoFactory.GetCollectionFromDatabase<RPESGResearchState>(clientDWConnectionString));


            var coverageCompanies = await step.GetResearchCompaniesAndCoverageCompanies(corporate);

            var universes = await step.ValidateDefaultReferenceUniverses(
                coverageCompanies, 
                MongoFactory.GetCollectionFromDatabase<ReferenceUniverse>(clientDWConnectionString)).ConfigureAwait(false);

            Assert.NotEqual(universes.Count, 0);
        }
    }

    public class DefaultWeightMatrixTest
    {
        private readonly DefaultReferenceUniverseProcessor sut;
        private readonly SyncContext context;
        private readonly string clientDWConnectionString;

        public DefaultWeightMatrixTest()
        {
            context = TestSyncContextFactoy.Create();
            clientDWConnectionString = context.GAConnectionStrings["ClientDW"];

            sut = new DefaultReferenceUniverseProcessor(MongoFactory.GetCollectionFromDatabase<ReferenceUniverse>(clientDWConnectionString), MongoFactory.GetCollectionFromDatabase<CorporateData>(clientDWConnectionString));
        }

        [Fact]
        public async Task TestDefaultReferenceUniverse()
        {
            var weightMatricesRepository = new RepositoryCollection<WeightMatrix>(clientDWConnectionString);

            var esgDefaultProfileManagement = new ESGProfileManagement(new RepositoryCollection<Entities.ESGRatings.ESGProfile>(context.GAConnectionStrings["ClientPlatform"]), new RepositoryCollection<ReferenceUniverse>(clientDWConnectionString), weightMatricesRepository);

            var defaultProfile = esgDefaultProfileManagement.AssureEsgProfile();

            if (defaultProfile == null)
            {
                throw new NullReferenceException("can't find default profile");
            }

            await sut.UpdateReferenceUniverseContent(defaultProfile.ReferenceUniverseId);

        }
    }


    public class ESGWeightMatrixValidation
    {
        private class MockCorporateDataLoader : CorporateDataLoader
        {
            public MockCorporateDataLoader(IMongoCollection<CorporateData> collection) : base(collection)
            {
            }
            public override async Task ProcessAsync(Func<CorporateDataInfo, Task> process)
            {
                await process(new CorporateDataInfo { CompanyName = "Test", Id = new Guid("653f2605-2235-4634-9e8f-68393bdfd33a") });
            }
        }

        private ESGRawScoresWeightsValidator sut;
        readonly ITestOutputHelper output;

        public ESGWeightMatrixValidation(ITestOutputHelper output)
        {
            this.output = output;
        }

        [Fact]
        public async Task Test()
        {

            var context = TestSyncContextFactoy.Create();
            var clientDWConnectionString = context.GAConnectionStrings["ClientDW"];
            sut = new ESGRawScoresWeightsValidator(new MockCorporateDataLoader(MongoFactory.GetCollectionFromDatabase<CorporateData>(clientDWConnectionString)), 
                MongoFactory.GetCollectionFromDatabase<ESG.Entities.CompanyWeights>(clientDWConnectionString),
                MongoFactory.GetCollectionFromDatabase<RPCompanyESGComputationResult>(clientDWConnectionString), 
                new CompanyWeightsValidator(), 
                output.WriteLine);
            await sut.ProcessAllSecurablesAsync(new Dictionary<Guid, AccountEsgProfileMatrixAssociations>
            {
                { Guid.Empty,
                new AccountEsgProfileMatrixAssociations(null,null,Guid.Empty,"Default")
            } }
            , new TemporaryDataSetBuilder()).ConfigureAwait(false);
        }

    }
}
